package com.xb.cloud.shopping.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.xb.cloud.common.JsonUtils;
import com.xb.cloud.common.constant.DbConstants;
import com.xb.cloud.company.service.client.CompanyService;
import com.xb.cloud.gateway.client.ReturnCodes;
import com.xb.cloud.gateway.client.ReturnUtils;
import com.xb.cloud.gateway.client.RtnInfo;
import com.xb.cloud.merchant.service.client.MerchantService;
import com.xb.cloud.order.service.client.ProductStockService;
import com.xb.cloud.product.merchant.service.client.ShopService;
import com.xb.cloud.product.merchant.service.client.bo.ShopSkuBo;
import com.xb.cloud.product.service.client.SkuService;
import com.xb.cloud.service.client.ServiceReturnInfo;
import com.xb.cloud.service.client.ServiceReturnUtils;
import com.xb.cloud.shopping.client.vo.CheckOutInputVo;
import com.xb.cloud.shopping.model.ShoppingCartItem;
import com.xb.cloud.shopping.service.OrderValidatorService;
import com.xb.cloud.user.service.client.EndUserService;
import com.xb.cloud.user.service.client.ShoppingCartService;
import com.xb.cloud.user.service.client.bo.EndUserBo;
import com.xb.cloud.user.service.client.bo.EndUserCartBo;
import com.xb.cloud.user.service.client.bo.ProductSkuStockBo;

@Service
public class OrderValidatorServiceImpl implements OrderValidatorService {

	@Resource
	ShoppingCartService shoppingCartService;

	@Resource
	SkuService skuService;

	@Resource
	ProductStockService productStockService;

	@Resource
	CompanyService companyService;

	@Resource
	MerchantService merchantService;

	@Resource
	ShopService shopService;

	@Resource
	EndUserService endUserService;

	/**
	 * 1. 验证下单商品列表为空<br/>
	 * 2. 验证购物车是否被修改（a.购物车被清空、不存在、被删除，b.下单所选商品被移除购物车）<br/>
	 * 3. 将下单商品数量改为数据库商品数量，保持一致<br/>
	 * 
	 * @Title validateShoppingCartInfo
	 * @param cartCheckOutVo
	 * @return
	 */
	@Override
	public RtnInfo validateShoppingCartInfo(CheckOutInputVo cartCheckOutVo) {
		// 验证下单所选的商品列表是否为空
		List<ShoppingCartItem> checkoutItemList = cartCheckOutVo.getItemList();
		if (CollectionUtils.isEmpty(checkoutItemList)) {
			return ReturnUtils.error(ReturnCodes.CHECKOUT_EMPTY_SKU);
		}

		EndUserCartBo endUserCartBo = new EndUserCartBo();
		endUserCartBo.setCompanyId(cartCheckOutVo.getCompanyId());
		endUserCartBo.setEndUserId(cartCheckOutVo.getCurrentUserId());
		EndUserCartBo dbEndUserCart = shoppingCartService.getEndUserCart(endUserCartBo);

		String cartValues = dbEndUserCart.getCartValues();
		List<ShoppingCartItem> dbCartItemList = JsonUtils.toObjectArray(cartValues, ShoppingCartItem.class);

		// 验证数据库购物车是否修改
		if (dbEndUserCart == null || CollectionUtils.isEmpty(dbCartItemList)) {
			// 购物车被删除或被清空
			return ReturnUtils.error(ReturnCodes.SHOPPINGCART_CHANGED);
		}

		// 将列表变成sku的map
		Map<Long, ShoppingCartItem> skuItemMap = new HashMap<>();
		for (ShoppingCartItem shoppingCartItem : dbCartItemList) {
			skuItemMap.put(shoppingCartItem.getSkuId(), shoppingCartItem);
		}

		// 检查前台购物车数据和数据库数据是否相同
		for (ShoppingCartItem checkoutItem : checkoutItemList) {
			ShoppingCartItem dbCartItem = skuItemMap.get(checkoutItem.getSkuId());
			if (dbCartItem == null) {
				// 商品已被删除
				return ReturnUtils.error(ReturnCodes.SHOPPINGCART_CHANGED);
			}
			// 将下单商品数量改为数据库数量
			checkoutItem.setNum(dbCartItem.getNum());
		}

		return ReturnUtils.success();
	}

	/**
	 * 验证下单商品sku是否可售<br/>
	 * 1. sku下架，删除。数据库中isCanSale=false <br/>
	 * 2. sku库存不足。<br/>
	 * 
	 * @Title checkSkusCanSale
	 * @param checkoutItemList
	 * @return unavailableSkus:返回不可售sku列表 <br/>
	 *         outStockSkus：返回库存不足sku列表 <br/>
	 *         更新checkoutItem的shopId,salePrice,defaultPicURL
	 */
	@Override
	public RtnInfo checkSkusCanSale(CheckOutInputVo cartCheckOutVo, List<ShoppingCartItem> checkoutItemList,
			List<ShopSkuBo> shopSkuList) {
		if (CollectionUtils.isEmpty(shopSkuList)) {
			return ReturnUtils.error(ReturnCodes.CHECKOUT_EMPTY_SKU);
		}

		long companyId = cartCheckOutVo.getCompanyId();
		ServiceReturnInfo returnInfo = companyService.isValidCompany(companyId);
		if (ServiceReturnUtils.isSuccess(returnInfo)) {
			if (!(Boolean) returnInfo.getData()) {
				return ReturnUtils.error(ReturnCodes.COMPANY_INVALID);
			}
		}

		long currentUserId = cartCheckOutVo.getCurrentUserId();
		returnInfo = endUserService.getEndUserById(currentUserId);
		if (ServiceReturnUtils.isSuccess(returnInfo)) {
			if (returnInfo.getData() == null) {
				return ReturnUtils.error(ReturnCodes.ENDUSER_INVALID);
			} else {
				EndUserBo endUserBo = (EndUserBo) returnInfo.getData();
				if (DbConstants.isTrue(endUserBo.getIsDeleted()) || !DbConstants.isTrue(endUserBo.getIsEnabled())) {
					return ReturnUtils.error(ReturnCodes.ENDUSER_INVALID);
				}
			}
		}

		Set<Long> merchantSet = new HashSet<>();
		Set<Long> shopSet = new HashSet<>();
		Map<Long, ShopSkuBo> shopSkuMap = new HashMap<>();
		for (ShopSkuBo shopSkuBo : shopSkuList) {
			shopSkuMap.put(shopSkuBo.getSkuId(), shopSkuBo);
			merchantSet.add(shopSkuBo.getMerchantId());
			shopSet.add(shopSkuBo.getShopId());
		}

		if (merchantSet.size() != 1) {
			return ReturnUtils.error(ReturnCodes.MERCHANT_MULTIPLE);
		} else {
			Long mercahntId = merchantSet.iterator().next();
			returnInfo = merchantService.isValidMerchant(mercahntId);
			if (ServiceReturnUtils.isSuccess(returnInfo)) {
				if (!(Boolean) returnInfo.getData()) {
					return ReturnUtils.error(ReturnCodes.MERCHANT_INVALID);
				}
			}
		}
		if (shopSet.size() != 1) {
			return ReturnUtils.error(ReturnCodes.SHOP_MULTIPLE);
		} else {
			Long shopId = shopSet.iterator().next();
			returnInfo = shopService.isValidShop(shopId);
			if (ServiceReturnUtils.isSuccess(returnInfo)) {
				if (!(Boolean) returnInfo.getData()) {
					return ReturnUtils.error(ReturnCodes.SHOP_INVALID);
				}
			}
		}

		List<ShopSkuBo> unavailableSkus = new ArrayList<>();
		List<ShopSkuBo> outStockSkus = new ArrayList<>();

		for (ShoppingCartItem checkoutItem : checkoutItemList) {
			ShopSkuBo shopSkuBo = shopSkuMap.get(checkoutItem.getSkuId());
			Byte isCanSale = shopSkuBo.getIsCanSale();
			if (!DbConstants.isTrue(isCanSale)) {
				unavailableSkus.add(shopSkuBo);
				continue;
			}

			boolean stockEnough = checkSkuStock(shopSkuBo.getShopId(), shopSkuBo.getProductId(), checkoutItem.getNum());
			if (!stockEnough) {
				outStockSkus.add(shopSkuBo);
				continue;
			}

		}

		Map<String, List<ShopSkuBo>> skuMap = new HashMap<>();
		skuMap.put("unavailableSkus", unavailableSkus);
		skuMap.put("outStockSkus", outStockSkus);

		if (!CollectionUtils.isEmpty(unavailableSkus)) {
			return ReturnUtils.error(skuMap, ReturnCodes.SKU_CANNOT_SALE);
		}
		if (!CollectionUtils.isEmpty(outStockSkus)) {
			return ReturnUtils.error(skuMap, ReturnCodes.SKU_STOCK_NOT_ENOUGH);
		}

		return ReturnUtils.success();
	}

	/**
	 * 验证sku库存， 由shopId+productId确定sku
	 * 
	 * @Title checkSkuStock
	 * @param shopId
	 * @param productId
	 * @param num
	 * @return
	 */
	private boolean checkSkuStock(Long shopId, Long productId, int num) {
		ServiceReturnInfo serviceReturnInfo = productStockService.getProductStockByProductShopWarehouse(productId,
				shopId, DbConstants.DEFAULT_WAREHOUSE_ID);
		if (ServiceReturnUtils.isSuccess(serviceReturnInfo)) {
			if (serviceReturnInfo.getData() == null) {
				return false;
			}

			ProductSkuStockBo skuStockBo = (ProductSkuStockBo) serviceReturnInfo.getData();
			if (!DbConstants.isTrue(skuStockBo.getIsEnabled())) {
				return false;
			}

			Long realFrozenStockNum = skuStockBo.getRealFrozenStockNum();// 实际冻结库存
			Long realStockNum = skuStockBo.getRealStockNum();// 实际库存
			// 可用库存 = 实际库存 - 实际冻结库存
			Long availableStock = realStockNum - realFrozenStockNum;
			if (availableStock.intValue() < num) {
				return false;
			}
		}

		return true;
	}

}
